#include "entities/city.h"

#include <algorithm>
#include <math.h>

#include "gamestate.h"

#include "entities/building.h"
#include "entities/tile.h"

City::City(int index, int owner):Improvement(){
    model_name = "city";
    this->index = index;
    canContainUnits = true;
    name = "My City";
    population = 10000;
    stockpiled_food = 0;
}

void City::Select(){
    std::cout<<"Name: "<<name<<std::endl;
    Improvement::Select();
}

void City::EndTurn(){
//    std::cout<<"Buildings in City:\n";
//    for(int id : buildings){
//        std::cout<<gamestate->GetBuilding(id)->GetName()<<std::endl;
//    }
}

bool City::GrowPopulation(){
    std::set<int> province = gamestate->GetProvince(GetID());
    bool growing = false;

//    std::for_each(province.begin(), province.end(), [&stockpiled_food](int index){
//            if(gamestate->GetTileByIndex(index)->GetTerrainType() == "farmland"){ stockpiled_food++; }
//        } );
//
//    stockpiled_food -= population;
//    if(stockpiled_food > 10){// + population*population){
//        population++;
//        stockpiled_food = 0;
//        growing = true;
//    }
    return growing;
}

float City::GetAdministrativeDistance(){
    float admin_dist = 0;
    for(int id : buildings){
        admin_dist += gamestate->GetBuilding(id)->GetAdministrativeDistance();
    }
    return admin_dist;
}

float City::GetFarmingDistance(){
    float farming_distance = 0;
    for(int id : GetBuildingIDs()){
        farming_distance += gamestate->GetBuilding(id)->GetFarmingDistance();
    }
    return farming_distance;
}

void City::DoImprovementConstruction(){
    if(improvement_construction_queue.size() > 0){
        Improvement* improvement = gamestate->GetImprovement(improvement_construction_queue.at(0));

        improvement->DoBuildingConstruction();
        if(improvement->IsPrimaryBuildingComplete()){
            BeginNextImprovementConstruction();
        }
    }
}

void City::BeginNextImprovementConstruction(){
    improvement_construction_queue.erase(improvement_construction_queue.begin());
    if(improvement_construction_queue.size()){
        gamestate->GetImprovement(improvement_construction_queue.at(0))->SetConstructionPaused(false);
    }
}

void City::AppendImprovementConstructionQueue(int id){
    bool pause;
    improvement_construction_queue.size() ? pause = true : pause = false;
    if(improvement_construction_queue.size() > 0){
        gamestate->GetImprovement(id)->SetConstructionPaused(true);
    }
    improvement_construction_queue.push_back(id);
}

void City::PrioritiseImprovementConstruction(int id){
    for(auto iter = std::begin(improvement_construction_queue); iter != std::end(improvement_construction_queue); ++iter){
        if(*iter == id){
            improvement_construction_queue.erase(iter);
            break;
        }
    }
    improvement_construction_queue.insert(improvement_construction_queue.begin(), id);
}

void City::UpdateFarms(){
    float farming_distance = GetFarmingDistance();

    for(int index : gamestate->GetProvince(GetID())){
        Tile* tile = gamestate->GetTileByIndex(index);
        if(tile->GetDistanceToFreshWater() <= farming_distance and tile->GetImprovementID() == -1){
            tile->SetTerrain("farmland");
        }
    }
}
